package com.techsoul.common.core.util.codec;

import com.techsoul.common.core.pojo.JwtPlayload;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang3.ObjectUtils;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Date;

public class JwtUtils {

    /**
     * 私钥加密token
     *
     * @param jwtPlayload 载荷中的数据
     * @param privateKey  私钥
     * @param expiration  过期时间，单位毫秒
     * @return
     * @throws Exception
     */
    public static String generateToken(JwtPlayload jwtPlayload, PrivateKey privateKey, Long expiration) {
        Long currentTimeMillis = System.currentTimeMillis();
        return Jwts.builder()
                .setId(jwtPlayload.getUserId()) // 令牌 ID
                .setSubject(jwtPlayload.getUserName()) // 令牌身份主体
                .setIssuedAt(new Date(currentTimeMillis)) // 令牌签发时间
                .setExpiration(new Date(currentTimeMillis + expiration)) // 令牌过期时间
                .signWith(SignatureAlgorithm.RS256, privateKey) // 签名方式和签名私钥
                .claim("avatar", jwtPlayload.getAvatar()) // 不敏感的其他信息，例如：用户头像
                .compact();
    }

    /**
     * 私钥加密token
     *
     * @param jwtPlayload 载荷中的数据
     * @param privateKey  私钥字节数组
     * @param expiration  过期时间，单位毫秒
     * @return
     * @throws Exception
     */
    public static String generateToken(JwtPlayload jwtPlayload, byte[] privateKey, Long expiration) throws Exception {
        Long currentTimeMillis = System.currentTimeMillis();
        return Jwts.builder()
                .setId(jwtPlayload.getUserId()) // 令牌 ID
                .setSubject(jwtPlayload.getUserName()) // 令牌身份主体
                .setIssuedAt(new Date(currentTimeMillis)) // 令牌签发时间
                .setExpiration(new Date(currentTimeMillis + expiration)) // 令牌过期时间
                .signWith(SignatureAlgorithm.RS256, RsaUtils.getPrivateKey(privateKey)) // 签名方式和签名私钥
                .claim("avatar", jwtPlayload.getAvatar()) // 不敏感的其他信息，例如：用户头像
                .compact();
    }

    /**
     * 公钥解析token
     *
     * @param token     用户请求中的token
     * @param publicKey 公钥
     * @return
     * @throws Exception
     */
    private static Jws<Claims> parserToken(String token, PublicKey publicKey) {
        return Jwts.parser()
                .setSigningKey(publicKey)
                .parseClaimsJws(token);
    }

    /**
     * 公钥解析token
     *
     * @param token     用户请求中的token
     * @param publicKey 公钥字节数组
     * @return
     * @throws Exception
     */
    private static Jws<Claims> parserToken(String token, byte[] publicKey) throws Exception {
        return Jwts.parser()
                .setSigningKey(RsaUtils.getPublicKey(publicKey))
                .parseClaimsJws(token);
    }

    /**
     * 获取token 中的载荷信息
     *
     * @param token     令牌
     * @param publicKey 公钥
     * @return 载荷信息
     * @throws Exception
     */
    public static JwtPlayload getJwtPlayload(String token, PublicKey publicKey) throws Exception {
        Jws<Claims> claimsJws = parserToken(token, publicKey);
        Claims body = claimsJws.getBody();
        return new JwtPlayload(
                ObjectUtils.toString(body.getId()),
                ObjectUtils.toString(body.getSubject()),
                ObjectUtils.toString(body.get("avatar"))
        );
    }

    /**
     * 获取token 中的载荷信息
     *
     * @param token     令牌
     * @param publicKey 公钥
     * @return 载荷信息
     * @throws Exception
     */
    public static JwtPlayload getJwtPlayload(String token, byte[] publicKey) throws Exception {
        Jws<Claims> claimsJws = parserToken(token, publicKey);
        Claims body = claimsJws.getBody();
        return new JwtPlayload(
                ObjectUtils.toString(body.getId()),
                ObjectUtils.toString(body.getSubject()),
                ObjectUtils.toString(body.get("avatar"))
        );
    }

}